home *** CD-ROM | disk | FTP | other *** search
Wrap
/* File: fat_adv.c Copyright (C) 1998-2004 Christophe GRENIER <grenier@cgsecurity.org> This software is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <stdio.h> #include <ctype.h> /* toupper */ #include <string.h> #include <stdlib.h> #include <time.h> #include <sys/stat.h> #include "types.h" #include "common.h" #include "fat.h" #include "lang.h" #include "fnctdsk.h" #include "testdisk.h" #include "intrface.h" #include "dir.h" #include "fat_dir.h" typedef struct info_sector_cluster t_sector_cluster; struct info_sector_cluster { unsigned int sector; unsigned int cluster; }; struct info_offset { dword offset; unsigned int nbr; unsigned int fat_type; }; typedef struct info_offset t_info_offset; typedef struct info_cluster_offset t_cluster_offset; struct info_cluster_offset { unsigned int cluster_size; dword offset; unsigned int nbr; unsigned int first_sol; }; static upart_type_t fat_find_info(t_param_disk *disk_car,unsigned int*reserved, unsigned int*fat_length, const t_diskext *partition,const dword max_offset,const int p_fat12,const int p_fat16,const int p_fat32,const int debug,const int dump_ind,const int interface); static int fat_find_type(t_param_disk *disk_car,const t_diskext *partition,const dword max_offset,const int p_fat12,const int p_fat16,const int p_fat32,const int debug,const int dump_ind,const int interface,unsigned int *nbr_offset,t_info_offset *info_offset); static unsigned int fat_find_fat_start(const unsigned char *buffer,const int p_fat12, const int p_fat16, const int p_fat32,dword*fat_offset); static int create_fat_boot_sector(t_param_disk *disk_car, t_diskext *partition, const unsigned int reserved, const int debug, const unsigned int dir_entries, const dword root_cluster, const unsigned int cluster_size, const unsigned int fat_length,const int interface, const upart_type_t upart_type); static unsigned int fat32_find_root_cluster(t_param_disk *disk_car,const t_diskext *partition,const unsigned int cluster_size, const dword no_of_cluster,const unsigned int offset, const int unsigned reserved,const int interface, const int debug); static int write_FAT_boot_code_aux(unsigned char *buffer); static int find_cluster_size(t_param_disk *disk_car, t_diskext *partition, const int debug, const int dump_ind,const int interface, unsigned int *cluster_size, dword *offset); static int find_dir_entries(t_param_disk *disk_car,const t_diskext *partition, const unsigned int offset,const int debug); static int find_cluster_size_aux(const t_sector_cluster *sector_cluster, const unsigned int nbr_sector_cluster,unsigned int *cluster_size, dword *offset, const int debug); static int analyse_dir_entries(t_param_disk *disk_car,const t_diskext *partition, const unsigned int offset, const int debug); static int analyse_dir_entries2(t_param_disk *disk_car,const t_diskext *partition, const unsigned int reserved, const unsigned int fat_length,const int debug, unsigned int root_size_max,const upart_type_t upart_type); static int calcul_cluster_size(const upart_type_t upart_type, const dword data_size, const unsigned int fat_length); static inline int check_entree(const unsigned char *entree); /* The goal is to identify the begining of the two FAT * TestDisk assumes that * - fragmentation is low * - free cluster are unusual in the beginning of a FAT * - small files are unsual at the beginning of a FAT * If fragmentation, EOC(End Of Cluster) or free cluster, increments nb_frag. * */ /* * 0 entree is free * 1 entree is used * 2 not an entry * */ static inline int check_entree(const unsigned char *entree) { int i; if((entree[0xB]&ATTR_EXT_MASK)==ATTR_EXT) return 1; /* ecrit_rapport("check_entree %02x\n",*(entree+0)); */ if(entree[0]==0) { for(i=0;i<0x20;i++) if(*(entree+i)!='\0') return 2; return 0; } if(entree[0]==0x20) return 2; if(entree[0]==0xE5) return 1; for(i=0;i<8+3;i++) { if((*(entree+i)>=0x06 && *(entree+i)<=0x1f)|| (*(entree+i)>=0x3a && *(entree+i)<=0x3f)|| (*(entree+i)>='a' && *(entree+i)<='z')) return 2; switch(*(entree+i)) { case 0x1: case 0x2: case 0x3: case 0x4: case 0x22: case 0x2A: case 0x2B: case 0x2C: case 0x2E: case 0x2F: case 0x5B: case 0x5C: case 0x5D: case 0x7C: /*ecrit_rapport("check_entree bad %c (%02x)\n",*(entree+i),*(entree+i)); */ return 2; default: /*ecrit_rapport("check_entree good %c (%02x)\n",*(entree+i),*(entree+i)); */ break; } } return 1; } /* */ dword get_subdirectory(t_param_disk *disk_car,const dword hd_offset,const dword i) { unsigned char buffer[SECTOR_SIZE]; if(disk_car->read(disk_car,1, &buffer, hd_offset)) { ecrit_rapport(msg_ROOT_CLUSTER_RERR); return 1; } /* dump(stdscr,buffer,SECTOR_SIZE); */ /* 12345678123*/ if(strncmp(&buffer[0],". ",8+3)!=0) return 1; if((unsigned)((buffer[0x15]<<24)|(buffer[0x14]<<16)|(buffer[0x1B]<<8)|buffer[0x1A])!=i) return 1; /* 12345678123*/ if(strncmp(&buffer[0x20],".. ",8+3)!=0) return 1; return (buffer[0x35]<<24)+(buffer[0x34]<<16)+(buffer[0x3B]<<8)+buffer[0x3A]; } static unsigned int fat32_find_root_cluster(t_param_disk *disk_car,const t_diskext *partition,const unsigned int cluster_size, const dword no_of_cluster,const unsigned int offset, const int unsigned reserved,const int interface, const int debug) { if(debug) ecrit_rapport("fat32_find_root_cluster(cluster_size=%u,no_of_cluster=%lu,offset=%u,reserved=%u)\n",cluster_size,no_of_cluster,offset,reserved); if(cluster_size==0) return 0; { dword root_cluster; unsigned char buffer[cluster_size*SECTOR_SIZE]; int ind_stop=FALSE; dword root_cluster_second_choice=0; if(interface) { wmove(stdscr,22,0); wstandout(stdscr); waddstr(stdscr," Stop "); wstandend(stdscr); } for(root_cluster=2;(root_cluster<2+no_of_cluster)&&!ind_stop;root_cluster++) { if(interface&&(root_cluster%71)==0) { wmove(stdscr,9,0); wclrtoeol(stdscr); wdoprintf(stdscr,"Search root cluster %10lu/%lu",root_cluster,2+no_of_cluster); wrefresh(stdscr); switch(wgetch_nodelay(stdscr)) { case KEY_ENTER: #ifdef PADENTER case PADENTER: #endif case '\n': case '\r': case 's': case 'S': ind_stop=1; break; } } /* */ if(disk_car->read(disk_car,cluster_size, &buffer, partition->lba+offset+(root_cluster-2)*cluster_size)==0) { if(debug>1) ecrit_rapport("fat32_find_root_cluster test cluster=%lu\n",root_cluster); /* dump(stdscr,buffer,SECTOR_SIZE); */ if(strncmp(&buffer[0],". ",8+3)!=0) { unsigned int i,found=1; int etat=0,nb_subdir=0,nb_subdir_ok=0; for(i=0;found && (i<16*cluster_size);i++) { int res=check_entree(&buffer[i*0x20]); if(debug>2) ecrit_rapport("fat32_find_root_cluster root_cluster=%lu i=%u etat=%d res=%d\n",root_cluster,i,etat,res); switch(res) { case 0: if(etat==0) etat=1; break; case 1: if(etat==1) { etat=2; found=0; } break; case 2: found=0; break; } if((buffer[i*0x20]!=DELETED_FLAG) && (buffer[i*0x20+0xB]==ATTR_DIR)) /* Test directory */ { nb_subdir++; /* ecrit_rapport("directory %s\n",&buffer[i*0x20]); */ } } for(i=0;found && (i<16*cluster_size);i++) { if((buffer[i*0x20]!=DELETED_FLAG) && (buffer[i*0x20+0xB]==ATTR_DIR)) /* Test directory */ { dword cluster=(buffer[i*0x20+0x15]<<24)+(buffer[i*0x20+0x14]<<16)+ (buffer[i*0x20+0x1B]<<8)+buffer[i*0x20+0x1A]; /* ecrit_rapport("cluster %ld\n",cluster); */ if((cluster>2+no_of_cluster)||(get_subdirectory(disk_car,partition->lba+offset+(cluster-2)*cluster_size,cluster)!=0)) { /* if(debug) */ /* ecrit_rapport("failed with %s\n",&buffer[i*0x20]); */ } else nb_subdir_ok++; } } if(found) { if((nb_subdir_ok>nb_subdir*0.90)&&(nb_subdir>=3)) { dword tmp=root_cluster; int back=0; /* To avoid an endless loop... */ /* Il faut ajouter un parcours arriere de la FAT * car on localise le dernier cluster du root_cluster */ if(debug) ecrit_rapport("cluster %lu, etat=%d, found=%d,nb_subdir=%d,nb_subdir_ok=%d\n",root_cluster,etat,found,nb_subdir,nb_subdir_ok); do { root_cluster=tmp; tmp=fat32_get_prev_cluster(disk_car,partition,reserved,root_cluster,no_of_cluster); if(debug) ecrit_rapport("prev cluster(%lu)=>%lu\n",root_cluster,tmp); if(tmp) { /* Check cluster number */ if((tmp<2) || (tmp>=2+no_of_cluster)) { ecrit_rapport("bad cluster number\n"); return root_cluster; } /* Read the cluster */ if(disk_car->read(disk_car,cluster_size, &buffer, partition->lba+offset+(tmp-2)*cluster_size)!=0) { ecrit_rapport("cluster can't be read\n"); return root_cluster; } /* Check if this cluster is a directory structure. FAT can be damaged */ for(i=0;i<16*cluster_size;i++) { if(check_entree(&buffer[i*0x20])!=1) { ecrit_rapport("cluster data is not a directory structure\n"); return root_cluster; } } } } while(tmp && (++back<10)); return root_cluster; } { t_file_data *dir_list; t_dir_data dir_data; WINDOW *window=newwin(0,0,0,0); /* full screen */ if(root_cluster_second_choice==0) root_cluster_second_choice=root_cluster; if(debug) ecrit_rapport("Potential root_cluster %lu\n",root_cluster); dir_list=dir_fat_aux(buffer,SECTOR_SIZE*cluster_size,cluster_size); aff_copy(window); dir_data.window=window; dir_data.debug=debug; dir_data.private_dir_data=NULL; dir_data.get_dir=fat32_dir; strncpy(dir_data.current_directory,"/",sizeof(dir_data.current_directory)); dir_aff(disk_car,partition,&dir_data,dir_list,root_cluster); delete_list_file(dir_list); delwin(window); #ifdef DJGPP wredrawln(stdscr,0,stdscr->_maxy); /* redrawwin def is boggus in pdcur24 */ #else redrawwin(stdscr); /* stdscr has been corrupted by window */ #endif if(ask_confirmation("Root directory found ? [Y/N] ")) { return root_cluster; } } } } else { /* Directory found */ dword cluster=(buffer[1*0x20+0x15]<<24)+(buffer[1*0x20+0x14]<<16)+ (buffer[1*0x20+0x1B]<<8)+buffer[1*0x20+0x1A]; if((memcmp(&buffer[0x20],".. ",8+3)==0) && (buffer[1*0x20+0xB]==ATTR_DIR)&&(cluster==0)) /* First-level directory */ { ecrit_rapport("First-level directory found at cluster %lu\n",root_cluster); } } } } ecrit_rapport("Search root cluster stopped: %10lu/%lu\n",root_cluster,no_of_cluster); } return 0; } static int find_dir_entries(t_param_disk *disk_car,const t_diskext *partition, const unsigned int offset,const int debug) { unsigned char buffer[SECTOR_SIZE]; unsigned int i,j; int etat=0; int sector_etat0=0; dword hd_offset; hd_offset=partition->lba+offset; for(i=0;(i<200)&&(etat!=2)&&(i<offset);i++) { if(disk_car->read(disk_car,1, &buffer, hd_offset)!=0) { ecrit_rapport("dir_entries: read error, dir_entries>=%u (%u sectors)\n",i*16,i); /* return 0; */ } else { for(j=15;j>0;j--) { if(debug>1) { ecrit_rapport("find_dir_entries sector=%u entree=%d etat=%d\n",offset-i,j,etat); } if(etat==0) { switch(check_entree(&buffer[j*0x20])) { case 0: break; case 1: sector_etat0=i; etat=1; break; case 2: return 0; } } else { switch(check_entree(&buffer[j*0x20])) { case 1: etat=1; break; case 0: case 2: return (i-1)*16; } } } } hd_offset--; } if((i==200) || (i==offset)) return 0; return (i-1)*16; } static int analyse_dir_entries(t_param_disk *disk_car,const t_diskext *partition, const unsigned int offset,const int debug) { unsigned char buffer[SECTOR_SIZE]; int i,j; int etat=0; int sector_etat1=0; dword hd_offset; hd_offset=partition->lba+offset; for(i=0;(i<200)&&(etat!=2);i++) { if(disk_car->read(disk_car,1, &buffer, hd_offset)!=0) { ecrit_rapport("dir_entries: read error, dir_entries>=%u (%u sectors)\n",i*16,i); /* return 0; */ } else { for(j=0;j<16;j++) { if(check_entree(&buffer[j*0x20])==0) { if(etat==0) { if(i*16+j>0) { etat=1; sector_etat1=i; if(debug>0) ecrit_rapport("dir_entries 0->1 %d\n",i*16+j); } else { return 0; } } } else if(etat==1) { if(i==sector_etat1) { return 0; } else { etat=2; if(debug>0) ecrit_rapport("dir_entries 1->2 %d\n",i*16+j); } } } } hd_offset++; } if(i==200) return 0; return (i-1)*16; } static int analyse_dir_entries2(t_param_disk *disk_car,const t_diskext *partition, const unsigned int reserved, const unsigned int fat_length,const int debug, unsigned int root_size_max,const upart_type_t upart_type) { t_file_data *current_file; t_file_data *dir_list=NULL; unsigned int nbr_sector; unsigned char *buffer_dir; if(root_size_max==0) { root_size_max=4096; } nbr_sector=(root_size_max+16-1)/16; buffer_dir=(unsigned char *)MALLOC(SECTOR_SIZE*nbr_sector); if(disk_car->read(disk_car, nbr_sector, buffer_dir, partition->lba+reserved+2*fat_length)!=0) { ecrit_rapport("FAT 1x"); ecrit_rapport(msg_ROOT_CLUSTER_RERR); return 0; } { dword start_data=reserved+2*fat_length+(root_size_max+16-1)/16; unsigned int cluster_size=calcul_cluster_size(upart_type,partition->part_size-start_data,fat_length); dir_list=dir_fat_aux(buffer_dir,SECTOR_SIZE*nbr_sector,cluster_size); } if(debug>1) { dir_aff_log(disk_car, partition, NULL, dir_list); } for(current_file=dir_list;(current_file!=NULL)&&(LINUX_S_ISDIR(current_file->filestat.st_mode)==0);current_file=current_file->next); if(current_file!=NULL) { unsigned long int new_inode=current_file->filestat.st_ino; unsigned int dir_entries; if(debug>1) { ecrit_rapport("Directory %s used inode=%lu\n",current_file->name,new_inode); } for(dir_entries=16;dir_entries<=root_size_max;dir_entries+=16) { dword start_data=reserved+2*fat_length+(dir_entries+16-1)/16; unsigned int cluster_size=calcul_cluster_size(upart_type,partition->part_size-start_data,fat_length); if(debug>1) { ecrit_rapport("dir_entries %u, cluster_size %u\n",dir_entries,cluster_size); } if(disk_car->read(disk_car, 1, buffer_dir, partition->lba+start_data+(new_inode-2)*cluster_size)==0) { if((memcmp(&buffer_dir[0],". ",8+3)==0)&&(memcmp(&buffer_dir[0x20],".. ",8+3)==0)) { dword cluster=(buffer_dir[0*0x20+0x15]<<24)+(buffer_dir[0*0x20+0x14]<<16)+ (buffer_dir[0*0x20+0x1B]<<8)+buffer_dir[0*0x20+0x1A]; dword cluster_prev=(buffer_dir[1*0x20+0x15]<<24)+(buffer_dir[1*0x20+0x14]<<16)+ (buffer_dir[1*0x20+0x1B]<<8)+buffer_dir[1*0x20+0x1A]; if(debug>1) { ecrit_rapport("Cluster %lu, directory .. found link to %lu\n",cluster,cluster_prev); } if(cluster_prev==0 && cluster==new_inode) { FREE(buffer_dir); delete_list_file(dir_list); return ((dir_entries+16-1)/16)*16; } } } } } else { ecrit_rapport("No directory found\n"); } FREE(buffer_dir); delete_list_file(dir_list); return root_size_max; } static int create_fat_boot_sector(t_param_disk *disk_car, t_diskext *partition, const unsigned int reserved, const int debug, const unsigned int dir_entries, const dword root_cluster, const unsigned int cluster_size, const unsigned int fat_length,const int interface, const upart_type_t upart_type) { unsigned char orgboot[3*SECTOR_SIZE]; unsigned char newboot[3*SECTOR_SIZE]; struct fat_boot_sector *org_fat_header=(struct fat_boot_sector *)&orgboot; struct fat_boot_sector *fat_header=(struct fat_boot_sector *)&newboot; int error=0; dword part_size=0; if(disk_car->read(disk_car,3, &orgboot, partition->lba)) { ecrit_rapport("create_fat_boot_sector: Can't read old boot sector\n"); memset(&orgboot,0,3*SECTOR_SIZE); } memcpy(&newboot,&orgboot,3*SECTOR_SIZE); if((le16(fat_header->marker)!=0xAA55)|| !((fat_header->ignored[0]==0xeb && fat_header->ignored[2]==0x90)||fat_header->ignored[0]==0xe9)) { write_FAT_boot_code_aux(newboot); } fat_header->sector_size[0]=SECTOR_SIZE & 0xFF; fat_header->sector_size[1]=SECTOR_SIZE>>8; fat_header->fats=2; fat_header->media=0xF8; fat_header->secs_track=disk_car->CHS.sector; fat_header->heads=disk_car->CHS.head+1; fat_header->marker=le16(0xAA55); if(!((fat_header->ignored[0]==0xeb&&fat_header->ignored[2]==0x90)||fat_header->ignored[0]==0xe9)) { fat_header->ignored[0]=0xeb; fat_header->ignored[2]=0x90; } /* I have seen a FAT32 partition that Win98 2nd edition was unable to read * because this name was missing! */ if(memcmp(fat_header->system_id,"MSDOS5.0",8) && memcmp(fat_header->system_id,"MSWIN4.0",8) && memcmp(fat_header->system_id,"MSWIN4.1",8)) memcpy(fat_header->system_id,"MSWIN4.1",8); if(partition->status==STATUS_LOG) fat_header->hidden=le32(63); else fat_header->hidden=le32(partition->lba); fat_header->cluster_size=cluster_size; fat_header->reserved=le16(reserved); /* The filesystem size can be smaller than the partition size */ switch(upart_type) { case UP_FAT12: part_size=le16(fat_header->reserved)+2*fat_length+dir_entries*32/SECTOR_SIZE+cluster_size*(fat_length*SECTOR_SIZE*2/3-2); break; case UP_FAT16: part_size=le16(fat_header->reserved)+2*fat_length+dir_entries*32/SECTOR_SIZE+cluster_size*(fat_length*SECTOR_SIZE/2-2); break; case UP_FAT32: part_size=le16(fat_header->reserved)+2*fat_length+cluster_size*(fat_length*SECTOR_SIZE/4-2); break; default: ecrit_rapport("create_fat_boot_sector: severe error\n"); exit(1); } if(part_size>partition->part_size) part_size=partition->part_size; if(part_size>0xFFFF) { fat_header->sectors[0]=0; fat_header->sectors[1]=0; fat_header->total_sect=le32(part_size); } else { fat_header->sectors[1]=part_size>>8; fat_header->sectors[0]=part_size; fat_header->total_sect=le32(0); } switch(upart_type) { case UP_FAT12: if((fat_length==0) || (dir_entries==0)) error=1; if((newboot[36]<0x80)||(newboot[36]>0x88)) newboot[36]=0x80; /* BS_DrvNum=0x80 */ newboot[37]=0; /* BS_Reserved1=0 */ newboot[38]=0x29; /* Boot sig=0x29 */ if(memcmp(newboot+FAT_NAME2,"FAT32",5)==0) memcpy(newboot+FAT_NAME2, " ",8); memcpy(newboot+FAT_NAME1,"FAT12 ",8); fat_header->fat_length=le16(fat_length); fat_header->dir_entries[1]=dir_entries>>8; fat_header->dir_entries[0]=dir_entries; if(check_volume_name(&newboot[FAT1X_PART_NAME],11)) newboot[FAT1X_PART_NAME]='\0'; break; case UP_FAT16: if((fat_length==0) || (dir_entries==0)) error=1; if((newboot[36]<0x80)||(newboot[36]>0x88)) newboot[36]=0x80; /* BS_DrvNum */ newboot[37]=0; /* BS_Reserved1=0 */ newboot[38]=0x29; /* Boot sig=0x29 */ if(memcmp(newboot+FAT_NAME2,"FAT32",5)==0) memcpy(newboot+FAT_NAME2, " ",8); memcpy(newboot+FAT_NAME1,"FAT16 ",8); fat_header->fat_length=le16(fat_length); fat_header->dir_entries[1]=dir_entries>>8; fat_header->dir_entries[0]=dir_entries; if(check_volume_name(&newboot[FAT1X_PART_NAME],11)) newboot[FAT1X_PART_NAME]='\0'; break; case UP_FAT32: if((fat_length==0) || (root_cluster==0)) error=1; fat_header->fat_length=le16(0); fat_header->dir_entries[0]=0; fat_header->dir_entries[1]=0; fat_header->fat32_length=le32(fat_length); /* Bits 0-3 -- Zero-based number of active FAT. Only valid if mirroring is disabled. Bits 4-6 -- Reserved. Bit 7 -- 0 means the FAT is mirrored at runtime into all FATs. -- 1 means only one FAT is active; it is the one referenced in bits 0-3. Bits 8-15 -- Reserved. */ fat_header->flags=le16(0); fat_header->version[0]=0; fat_header->version[1]=0; fat_header->root_cluster=le32(root_cluster); /* Sector number of FSINFO structure in the reserved area of the FAT32 volume. */ fat_header->info_sector=le16(1); fat_header->backup_boot=le16(6); memset(&fat_header->BPB_Reserved,0,sizeof(fat_header->BPB_Reserved)); if((fat_header->BS_DrvNum<0x80)||(fat_header->BS_DrvNum>0x87)) fat_header->BS_DrvNum=0x80; fat_header->BS_Reserved1=0; fat_header->BS_BootSig=0x29; if((memcmp(newboot+FAT_NAME1,"FAT12",5)==0) ||(memcmp(newboot+FAT_NAME1,"FAT16",5)==0)) memcpy(newboot+FAT_NAME1," ",8); memcpy(fat_header->BS_FilSysType, "FAT32 ",8); newboot[0x1FC]=0x00; /* part of the signature */ newboot[0x1FD]=0x00; memset(&newboot[SECTOR_SIZE],0,SECTOR_SIZE); newboot[SECTOR_SIZE]='R'; /* Signature RRaA */ newboot[SECTOR_SIZE+1]='R'; newboot[SECTOR_SIZE+2]='a'; newboot[SECTOR_SIZE+3]='A'; newboot[SECTOR_SIZE+0x1E4]='r'; /* Signature rrAa */ newboot[SECTOR_SIZE+0x1E5]='r'; newboot[SECTOR_SIZE+0x1E6]='A'; newboot[SECTOR_SIZE+0x1E7]='a'; /* Don't set the number of free cluster or the next free cluster */ newboot[SECTOR_SIZE+0x1E8]=0xFF; /* Free clusters on disk */ newboot[SECTOR_SIZE+0x1E9]=0xFF; newboot[SECTOR_SIZE+0x1EA]=0xFF; newboot[SECTOR_SIZE+0x1EB]=0xFF; newboot[SECTOR_SIZE+0x1EC]=0xFF; /* Next avaible clusters */ newboot[SECTOR_SIZE+0x1ED]=0xFF; newboot[SECTOR_SIZE+0x1EE]=0xFF; newboot[SECTOR_SIZE+0x1EF]=0xFF; newboot[SECTOR_SIZE+0x1FC]=0x00; /* End of Sector signature */ newboot[SECTOR_SIZE+0x1FD]=0x00; newboot[SECTOR_SIZE+0x1FE]=0x55; newboot[SECTOR_SIZE+0x1FF]=0xAA; newboot[2*SECTOR_SIZE+0x1FC]=0x00; /* End of Sector signature */ newboot[2*SECTOR_SIZE+0x1FD]=0x00; newboot[2*SECTOR_SIZE+0x1FE]=0x55; newboot[2*SECTOR_SIZE+0x1FF]=0xAA; if(check_volume_name(&newboot[FAT32_PART_NAME],11)) newboot[FAT32_PART_NAME]='\0'; break; default: ecrit_rapport("create_fat_boot_sector: severe error\n"); exit(1); } if(memcmp(newboot,orgboot,1*SECTOR_SIZE)) /* Only compare the first sector */ { ecrit_rapport(" New / Current boot sector"); dump_2fat_rapport(fat_header,org_fat_header,upart_type); ecrit_rapport("Extrapolated boot sector and current boot sector are different.\n"); } else { ecrit_rapport("Extrapolated boot sector and current boot sector are identical.\n"); } /* */ if(interface) { struct MenuItem menuSaveBoot[]= { { 'D', "Dump", "Dump sector" }, { 'L', "List", "List directories and files" }, { 'W', "Write","Write boot"}, { 'Q',"Quit","Quit this section"}, { 0, NULL, NULL } }; const char *options="DLQ"; int do_write=0; int do_exit=0; do { do_exit=0; aff_copy(stdscr); wmove(stdscr,4,0); wdoprintf(stdscr,"%s",disk_car->description(disk_car)); /* mvwaddstr(stdscr,5,0,msg_PART_HEADER2); */ wmove(stdscr,5,0); aff_part(stdscr,AFF_PART_ORDER,disk_car,partition); wmove(stdscr,8,0); if(memcmp(newboot,orgboot,SECTOR_SIZE)) /* Only compare the first sector */ { options="DLWQ"; dump_2fat_info(fat_header, org_fat_header, upart_type); wdoprintf(stdscr,"Extrapolated boot sector and current boot sector are different.\n"); if(error) { wdoprintf(stdscr,"Warning: Extrapolated boot sector have incorrect values.\n"); ecrit_rapport("Warning: Extrapolated boot sector have incorrect values.\n"); } } else { dump_fat_info(fat_header, upart_type); wdoprintf(stdscr,"Extrapolated boot sector and current boot sector are identical.\n"); } switch(toupper(wmenuSelect(stdscr,INTER_DUMP_Y, INTER_DUMP_X, menuSaveBoot,8,options,MENU_HORIZ|MENU_BUTTON|MENU_ACCEPT_OTHERS, 1))) { case 'W': if(strchr(options,'W')) do_write=1; break; case 'D': if(strchr(options,'D')) { dump2(stdscr,newboot,orgboot, upart_type==UP_FAT32?3*SECTOR_SIZE:SECTOR_SIZE); } break; case 'L': dir_partition_fat_aux(stdscr,disk_car, partition, debug, fat_header); break; case 'Q': do_exit=1; break; } } while(!do_write && !do_exit); if(do_write && ask_confirmation("Write FAT boot sector, confirm ? (Y/N)")) { int err=0; ecrit_rapport("Write new boot!\n"); /* Write boot sector and backup boot sector */ if(upart_type==UP_FAT32) { if(disk_car->write(disk_car,3, &newboot, partition->lba)!=0 || disk_car->write(disk_car,3, &newboot, partition->lba+le16(fat_header->backup_boot))!=0) err=1; } else { if(disk_car->write(disk_car,1, &newboot, partition->lba)!=0) err=1; } if(err==1) { display_message("Write error: Can't write new FAT boot sector\n"); } /* TestDisk don't correct the filesystem, use another utility */ } else ecrit_rapport("Don't write new boot!\n"); } return 0; } static int calcul_cluster_size(const upart_type_t upart_type, const dword data_size, const unsigned int fat_length) { /* ecrit_rapport("calcul_cluster_size data_size=%lu, fat_length=%u\n",data_size,fat_length); */ if(fat_length==0) return 0; switch(upart_type) { case UP_FAT12: return up2power(data_size/(fat_length*SECTOR_SIZE*2/3-1)); case UP_FAT16: return up2power(data_size/(fat_length*SECTOR_SIZE/2-1)); case UP_FAT32: return up2power(data_size/(fat_length*SECTOR_SIZE/4-1)); default: ecrit_rapport("calcul_cluster_size: severe error\n"); return 0; } } static unsigned int fat_find_fat_start(const unsigned char *buffer,const int p_fat12, const int p_fat16, const int p_fat32,dword*fat_offset) { t_info_offset info_offset[0x200]; unsigned int nbr_offset=0; if(p_fat12!=0) { unsigned int i; int low; int high; i=0; high=0; low=0; while(high<(SECTOR_SIZE-1)) { dword cluster=0; if(low==0) cluster=((buffer[high+1] & 0x0F) <<8) | buffer[high]; else cluster=(buffer[high+1] <<4) | ((buffer[high]&0xF0)>>4); if((cluster!=0) && ((cluster&0x0ff8)!=(unsigned)0x0ff8) && (((cluster-i-1)*3)%(2*SECTOR_SIZE)==0)) { unsigned int j; for(j=0;(j<nbr_offset)&&(info_offset[j].offset!=(cluster-i-1)*3/(2*SECTOR_SIZE))&&(info_offset[j].fat_type==12);j++); if(j<nbr_offset) info_offset[j].nbr++; else { info_offset[nbr_offset].offset=(cluster-i-1)*3/(2*SECTOR_SIZE); info_offset[nbr_offset].nbr=1; info_offset[nbr_offset].fat_type=12; nbr_offset++; } } if(low==0) low=1; else { high++; low=0; } high++; i++; } i=1; high=1; low=0; while(high<(SECTOR_SIZE-1)) { dword cluster=0; if(low==0) cluster=((buffer[high+1] & 0x0F) <<8) | buffer[high]; else cluster=(buffer[high+1] <<4) | ((buffer[high]&0xF0)>>4); if((cluster!=0) && ((cluster&0x0ff8)!=(unsigned)0x0ff8) && (((cluster-i-1)*3+1)%(2*SECTOR_SIZE)==0)) { unsigned int j; for(j=0;(j<nbr_offset)&&(info_offset[j].offset!=((cluster-i-1)*3+1)/(2*SECTOR_SIZE))&&(info_offset[j].fat_type==12);j++); if(j<nbr_offset) info_offset[j].nbr++; else { info_offset[nbr_offset].offset=((cluster-i-1)*3+1)/(2*SECTOR_SIZE); info_offset[nbr_offset].nbr=1; info_offset[nbr_offset].fat_type=12; nbr_offset++; } } if(low==0) low=1; else { high++; low=0; } high++; i++; } i=1; high=0; low=1; while(high<(SECTOR_SIZE-1)) { dword cluster=0; if(low==0) cluster=((buffer[high+1] & 0x0F) <<8) | buffer[high]; else cluster=(buffer[high+1] <<4) | ((buffer[high]&0xF0)>>4); if((cluster!=0) && ((cluster&0x0ff8)!=(unsigned)0x0ff8) && (((cluster-i-1)*3+2)%(2*SECTOR_SIZE)==0)) { unsigned int j; for(j=0;(j<nbr_offset)&&(info_offset[j].offset!=((cluster-i-1)*3+2)/(2*SECTOR_SIZE))&&(info_offset[j].fat_type==12);j++); if(j<nbr_offset) info_offset[j].nbr++; else { info_offset[nbr_offset].offset=((cluster-i-1)*3+2)/(2*SECTOR_SIZE); info_offset[nbr_offset].nbr=1; info_offset[nbr_offset].fat_type=12; nbr_offset++; } } if(low==0) low=1; else { high++; low=0; } high++; i++; } } if(p_fat16!=0) { unsigned int i,j; const word *p16=(const word*)buffer; unsigned int err=0; for(i=0; (i<SECTOR_SIZE/2)&&(err==0); i++) { dword cluster=le16(p16[i]); if(cluster==1) { err=1; } if((cluster!=0) && ((cluster&0x0fff8)!=(unsigned)0x0fff8)) { for(j=i+1; (j<SECTOR_SIZE/2)&&(err==0); j++) { if(cluster==le16(p16[j])) { err=1; } } } } if(err==0) { for(i=0; i<SECTOR_SIZE/2; i++) { dword cluster=le16(p16[i]); if((cluster!=0) && ((cluster&0x0fff8)!=(unsigned)0x0fff8)&&((cluster-i-1)%(SECTOR_SIZE/2)==0)) { for(j=0;(j<nbr_offset)&&(info_offset[j].offset!=(cluster-i-1)/(SECTOR_SIZE/2))&&(info_offset[j].fat_type==16);j++); if(j<nbr_offset) info_offset[j].nbr++; else { info_offset[nbr_offset].offset=(cluster-i-1)/(SECTOR_SIZE/2); info_offset[nbr_offset].nbr=1; info_offset[nbr_offset].fat_type=16; nbr_offset++; } } } } } if(p_fat32!=0) { unsigned int i,j; const dword *p32=(const dword*)buffer; unsigned int err=0; for(i=0; (i<SECTOR_SIZE/4)&&(err==0); i++) { dword cluster=le32(p32[i])&0x0FFFFFFF; if(cluster==1) { err=1; } if((cluster!=0) && ((cluster&0x0ffffff8)!=(unsigned)0x0ffffff8)) { for(j=i+1; (j<SECTOR_SIZE/4)&&(err==0); j++) { if(cluster==(le32(p32[j])&0x0FFFFFFF)) { err=1; } } } } if(err==0) { for(i=0; i<SECTOR_SIZE/4; i++) { dword cluster=le32(p32[i])&0x0FFFFFFF; if((cluster!=0) && ((cluster&0x0ffffff8)!=(unsigned)0x0ffffff8)&&((cluster-i-1)%(SECTOR_SIZE/4)==0)) { for(j=0;(j<nbr_offset)&&(info_offset[j].offset!=(cluster-i-1)/(SECTOR_SIZE/4))&&(info_offset[j].fat_type==32);j++); if(j<nbr_offset) info_offset[j].nbr++; else { info_offset[nbr_offset].offset=(cluster-i-1)/(SECTOR_SIZE/4); info_offset[nbr_offset].nbr=1; info_offset[nbr_offset].fat_type=32; nbr_offset++; } } } } } if(nbr_offset==0) return 0; { unsigned int j; unsigned int best_j=0; for(j=0;j<nbr_offset;j++) { if(info_offset[j].nbr>info_offset[best_j].nbr) best_j=j; } if(info_offset[best_j].nbr>10) { *fat_offset=info_offset[best_j].offset; return info_offset[best_j].fat_type; } } return 0; } /* TestDisk assumes BPB_media is 0xF8, standard value for fixed disk. * */ static int fat_find_type(t_param_disk *disk_car,const t_diskext *partition,const dword max_offset,const int p_fat12,const int p_fat16,const int p_fat32,const int debug,const int dump_ind,const int interface,unsigned int *nbr_offset,t_info_offset *info_offset) { dword offset; dword hd_offset; if(debug) ecrit_rapport("fat_find_type(partition,max_offset=%ld,p_fat12=%d,p_fat16=%d,p_fat32=%d,*f_fat12,*f_fat16,*f_fat32,debug=%d,dump_ind=%d)\n",max_offset,p_fat12,p_fat16,p_fat32,debug,dump_ind); for(offset=1,hd_offset=partition->lba+1;(offset<max_offset)&&(*nbr_offset<0x200);offset++,hd_offset++) { unsigned char buffer[SECTOR_SIZE]; if(interface && ((offset&0x1FF)==0)) { wmove(stdscr,8,0); wdoprintf(stdscr,"FAT : %s%s%s?\n",p_fat12?"12 ":"", p_fat16?"16 ":"", p_fat32?"32 ":""); wmove(stdscr,8,30); wclrtoeol(stdscr); /* before addstr for BSD compatibility */ wdoprintf(stdscr,"analyse %10lu/%lu",offset,max_offset); wrefresh(stdscr); } if(disk_car->read(disk_car,1, &buffer, hd_offset)!=0) { continue; } { dword fat_offset=0; unsigned int fat_type; fat_type=fat_find_fat_start(buffer,p_fat12,p_fat16,p_fat32,&fat_offset); if(fat_type!=0 && fat_offset<offset) { unsigned int j; if(debug>1) { ecrit_rapport("fat_find_fat_start FAT%u at %lu:%lu\n",fat_type,offset-fat_offset,offset); } for(j=0;(j<*nbr_offset)&&(info_offset[j].offset!=offset-fat_offset)&&(info_offset[j].fat_type==fat_type);j++); if(j<*nbr_offset) info_offset[j].nbr++; else { if(*nbr_offset<0x200) { info_offset[*nbr_offset].offset=offset-fat_offset; info_offset[*nbr_offset].nbr=1; info_offset[*nbr_offset].fat_type=fat_type; (*nbr_offset)++; } } } } } return 0; } static upart_type_t fat_find_info(t_param_disk *disk_car,unsigned int*reserved, unsigned int*fat_length, const t_diskext *partition,const dword max_offset,const int p_fat12,const int p_fat16,const int p_fat32,const int debug,const int dump_ind,const int interface) { unsigned int nbr_offset=0; t_info_offset info_offset[0x200]; upart_type_t upart_type=UP_UNK; fat_find_type(disk_car, partition,max_offset,p_fat12,p_fat16,p_fat32,debug,dump_ind,interface,&nbr_offset,&info_offset[0]); { unsigned int i; for(i=0;i<nbr_offset;i++) { ecrit_rapport("FAT%u at %lu(%u/%u/%u), nbr=%u\n",info_offset[i].fat_type,info_offset[i].offset, LBA2cylinder(disk_car,partition->lba+info_offset[i].offset), LBA2head(disk_car,partition->lba+info_offset[i].offset), LBA2sector(disk_car,partition->lba+info_offset[i].offset), info_offset[i].nbr); if((dump_ind>0) && (interface>0)) { unsigned char buffer[SECTOR_SIZE]; if(disk_car->read(disk_car,1, &buffer, partition->lba+info_offset[i].offset)==0) { dump(stdscr,buffer,SECTOR_SIZE); } } } } if(nbr_offset>0) { switch(info_offset[0].fat_type) { case 12: upart_type=UP_FAT12; break; case 16: upart_type=UP_FAT16; break; case 32: upart_type=UP_FAT32; break; } } switch(nbr_offset) { case 0: *fat_length=0; break; case 1: switch(upart_type) { case UP_FAT12: case UP_FAT16: *reserved=1; if(info_offset[0].offset>*reserved) *fat_length=info_offset[0].offset-*reserved; else *fat_length=0; break; case UP_FAT32: if(info_offset[0].offset==32 || info_offset[0].offset==33) *reserved=info_offset[0].offset; *fat_length=0; break; default: ecrit_rapport("fat_find_info: severe error\n"); return UP_UNK; } break; default: switch(upart_type) { case UP_FAT12: case UP_FAT16: *reserved=1; if(info_offset[0].offset==*reserved) *fat_length=info_offset[1].offset-info_offset[0].offset; else *fat_length=info_offset[0].offset-*reserved; break; case UP_FAT32: *reserved=info_offset[0].offset; *fat_length=info_offset[1].offset-info_offset[0].offset; if(*reserved==32 || *reserved==33 || comp_FAT(disk_car,partition,*fat_length,*reserved)==0) { } else { *reserved=0; *fat_length=0; } break; default: ecrit_rapport("fat_find_info: severe error\n"); return UP_UNK; } break; } return upart_type; } /* Using a couple of inodes of "." directory entries, get the cluster size and where the first cluster begins. * */ static int find_cluster_size(t_param_disk *disk_car, t_diskext *partition, const int debug, const int dump_ind,const int interface, unsigned int *cluster_size, dword *offset) { dword i; dword skip_sector; unsigned char buffer[SECTOR_SIZE]; int ind_stop=FALSE; unsigned int nbr_subdir=0; t_sector_cluster sector_cluster[10]; if(interface) { wmove(stdscr,22,0); wstandout(stdscr); waddstr(stdscr," Stop "); wstandend(stdscr); } /* 2 fats, maximum cluster size=128 */ skip_sector=(partition->part_size-32)/128*1.5/SECTOR_SIZE*2; ecrit_rapport("find_cluster_size skip_sector=%lu\n",skip_sector); for(i=skip_sector;(i<partition->part_size)&&!ind_stop&&(nbr_subdir<10);i++) { if(interface && ((i&0x1FF)==0)) { wmove(stdscr,9,0); wclrtoeol(stdscr); wdoprintf(stdscr,"Search subdirectory %10lu/%lu %u",i,partition->part_size,nbr_subdir); wrefresh(stdscr); switch(wgetch_nodelay(stdscr)) { case KEY_ENTER: #ifdef PADENTER case PADENTER: #endif case '\n': case '\r': case 's': case 'S': ind_stop=1; break; } } if(disk_car->read(disk_car,1, &buffer, partition->lba+i)==0) { if((memcmp(&buffer[0],". ",8+3)==0)&&(memcmp(&buffer[0x20],".. ",8+3)==0)) { dword cluster=(buffer[0*0x20+0x15]<<24)+(buffer[0*0x20+0x14]<<16)+ (buffer[0*0x20+0x1B]<<8)+buffer[0*0x20+0x1A]; ecrit_rapport("sector %lu, cluster %lu\n",i,cluster); sector_cluster[nbr_subdir].cluster=cluster; sector_cluster[nbr_subdir].sector=i; nbr_subdir++; } } } return find_cluster_size_aux(sector_cluster,nbr_subdir,cluster_size,offset,debug); } static int find_cluster_size_aux(const t_sector_cluster *sector_cluster, const unsigned int nbr_sector_cluster,unsigned int *cluster_size, dword *offset, const int debug) { if(nbr_sector_cluster<2) return 0; { unsigned int i,j; unsigned int nbr_sol=0; t_cluster_offset cluster_offset[nbr_sector_cluster*nbr_sector_cluster]; for(i=0;i<nbr_sector_cluster-1;i++) { for(j=i+1;j<nbr_sector_cluster;j++) { if(sector_cluster[j].cluster>sector_cluster[i].cluster) { unsigned int cluster_size_tmp=(sector_cluster[j].sector-sector_cluster[i].sector)/(sector_cluster[j].cluster-sector_cluster[i].cluster); switch(cluster_size_tmp) { case 1: case 2: case 4: case 8: case 16: case 32: case 64: case 128: if(sector_cluster[i].sector>(sector_cluster[i].cluster-2)*(*cluster_size)) { unsigned int sol_cur; unsigned int found=0; unsigned int offset_tmp=sector_cluster[i].sector-(sector_cluster[i].cluster-2)*cluster_size_tmp; for(sol_cur=0;(sol_cur<nbr_sol)&&!found;sol_cur++) { if(cluster_offset[sol_cur].cluster_size==cluster_size_tmp && cluster_offset[sol_cur].offset==offset_tmp) { if(cluster_offset[sol_cur].first_sol==i) { cluster_offset[sol_cur].nbr++; } /* ecrit_rapport("cluster_size=%u offset=%lu nbr=%u\n",cluster_offset[sol_cur].cluster_size,cluster_offset[sol_cur].offset,cluster_offset[sol_cur].nbr); */ found=1; } } if(!found) { cluster_offset[nbr_sol].cluster_size=cluster_size_tmp; cluster_offset[nbr_sol].offset=offset_tmp; cluster_offset[nbr_sol].nbr=1; cluster_offset[nbr_sol].first_sol=i; nbr_sol++; } } break; } } } } /* Show results */ { unsigned int nbr_max=0; unsigned int sol_cur; for(sol_cur=0;sol_cur<nbr_sol;sol_cur++) { if(debug>0) ecrit_rapport("cluster_size=%u offset=%lu nbr=%u\n",cluster_offset[sol_cur].cluster_size,cluster_offset[sol_cur].offset,cluster_offset[sol_cur].nbr); if(cluster_offset[sol_cur].nbr>nbr_max) { nbr_max=cluster_offset[sol_cur].nbr; *cluster_size=cluster_offset[sol_cur].cluster_size; *offset=cluster_offset[sol_cur].offset; } } if(nbr_max>0) { ecrit_rapport("Selected: cluster_size=%u offset=%lu nbr=%u\n",*cluster_size, *offset,nbr_max); return 1; } } } /* Failed */ return 0; } int rebuild_FAT_BS(t_param_disk *disk_car, t_diskext *partition, const int debug, const int dump_ind,const int interface) { dword start_data=0; dword data_size; unsigned int fat_length=0; dword fat_length_max; int p_fat12,p_fat16,p_fat32; unsigned int cluster_size_min=1; unsigned int cluster_size=0; dword max_offset; dword root_cluster=0; /* Initialized by fat32_find_root_cluster */ int upart_type; unsigned int dir_entries=0; unsigned int reserved=0; /* Initialized by fat32_free_info */ dword free_count=0; dword next_free=0; /* * Using partition size, check if partition can be FAT12, FAT16 or FAT32 * */ if(partition->part_size>(2*1024+1)*1024*2) { p_fat32=1; p_fat16=0; p_fat12=0; } else /* 1<<12 clusters * 8 secteurs/clusters= 32768 secteurs fat_length=((1<<12+1)*1.5/SECTOR_SIZE)+1=13; */ if(partition->part_size>=(1+2*13+32768+63)) { p_fat32=1; p_fat16=1; p_fat12=0; } else { p_fat32=0; p_fat16=1; p_fat12=1; } #ifdef TESTING p_fat32=1; p_fat16=1; p_fat12=1; #endif if(debug) { ecrit_rapport("\n"); aff_part_rapport(disk_car,partition); ecrit_rapport("rebuild_FAT_BS p_fat12 %d, p_fat16 %d, p_fat32 %d\n", p_fat12,p_fat16,p_fat32); } /* Set fat_length_max */ if(p_fat32) { /* Cluster 1k */ fat_length_max=partition->part_size/cluster_size_min*4/SECTOR_SIZE; } else if(p_fat16) { while(partition->part_size/cluster_size_min>(1<<16)) cluster_size_min*=2; fat_length_max=partition->part_size/cluster_size_min*2/SECTOR_SIZE; } else { while(partition->part_size/cluster_size_min>(1<<12)) cluster_size_min*=2; fat_length_max=partition->part_size/cluster_size_min*1.5/SECTOR_SIZE; } if(debug) { ecrit_rapport("cluster_size_min %u\n",cluster_size_min); ecrit_rapport("fat_length_max %ld\n", fat_length_max); } max_offset=fat_length_max+64; /* if(debug) ecrit_rapport("search_fat16(partition,max_offset=%d,p_fat12=%d,p_fat16=%d,p_fat32=%d,debug=%d,dump_ind=%d)\n",max_offset,p_fat12,p_fat16,p_fat32,debug,dump_ind); */ if(interface) { aff_copy(stdscr); wmove(stdscr,4,0); wdoprintf(stdscr,"%s",disk_car->description(disk_car)); /* mvwaddstr(stdscr,5,0,msg_PART_HEADER2); */ wmove(stdscr,5,0); aff_part(stdscr,AFF_PART_ORDER,disk_car,partition); wrefresh(stdscr); } upart_type=fat_find_info(disk_car,&reserved, &fat_length, partition,max_offset,p_fat12,p_fat16,p_fat32,debug,dump_ind,interface); if(interface) { wmove(stdscr,8,0); wclrtoeol(stdscr); switch(upart_type) { case UP_FAT12: waddstr(stdscr,"FAT : 12"); break; case UP_FAT16: waddstr(stdscr,"FAT : 16"); break; case UP_FAT32: waddstr(stdscr,"FAT : 32"); break; default: waddstr(stdscr,"No FAT found"); break; } } if((upart_type!=UP_FAT12 && upart_type!=UP_FAT16 && upart_type!=UP_FAT32)|| (fat_length==0)||(reserved==0)) { if(find_cluster_size(disk_car, partition, debug, dump_ind, interface,&cluster_size,&start_data)==0) { ecrit_rapport("Can't find cluster size\n"); return 0; } if((cluster_size<=0) || (partition->part_size<=start_data)) { ecrit_rapport("Can't find cluster size\n"); return 0; } { unsigned int no_of_cluster; no_of_cluster=(partition->part_size-start_data)/cluster_size; if(no_of_cluster<65525) { if(no_of_cluster<4085) { /* FAT12 */ ecrit_rapport("FAT : 12\n"); upart_type=UP_FAT12; } else { /* FAT16 */ ecrit_rapport("FAT : 16\n"); upart_type=UP_FAT16; } reserved=1; /* must be 1 */ dir_entries=find_dir_entries(disk_car,partition,start_data-1,debug); switch(dir_entries) { case 0: ecrit_rapport("dir_entries not found, should be 512\n"); dir_entries=512; break; case 512: if(debug) ecrit_rapport("dir_entries: %u\n",dir_entries); break; default: ecrit_rapport("dir_entries: %u (unusual value)\n",dir_entries); break; } fat_length=(start_data-reserved-((dir_entries-1)/16+1))/2; if(debug) ecrit_rapport("fat_length %u\n",fat_length); } else { /* FAT32*/ ecrit_rapport("FAT : 32\n"); upart_type=UP_FAT32; reserved=32; if((start_data&1)!=0) reserved+=1; fat_length=(start_data-reserved)/2; } if(debug) ecrit_rapport("fat_length %u\n",fat_length); } } if(interface) { if(fat_length==0) waddstr(stdscr," Can't find FAT length\n"); wrefresh(stdscr); } if(upart_type && (fat_length>1)) { start_data=reserved+2*fat_length; /* FAT1x: Find size of root directory */ if((upart_type==UP_FAT12) || (upart_type==UP_FAT16)) { int old_dir_entries=dir_entries; dir_entries=analyse_dir_entries(disk_car,partition,reserved+2*fat_length,debug); ecrit_rapport("dir_entries %u\n",dir_entries); dir_entries=analyse_dir_entries2(disk_car,partition,reserved,fat_length,debug,dir_entries,upart_type); ecrit_rapport("dir_entries %u\n",dir_entries); if(dir_entries==0) { if(old_dir_entries>0) fat_length=0; /* else { dir_entries=512; ecrit_rapport("analyse_dir_entries: use default dir_entries %u\n",dir_entries); } */ } start_data+=(dir_entries+16-1)/16; } if(partition->part_size<=start_data) { ecrit_rapport("Error part_size=%lu <= start_data=%lu\n",partition->part_size,start_data); return 0; } data_size=partition->part_size-start_data; /* Get Cluster Size */ { int old_cluster_size=cluster_size; cluster_size=calcul_cluster_size(upart_type,data_size,fat_length); if(debug) ecrit_rapport("cluster_size %u\n",cluster_size); if((cluster_size<=0)||(cluster_size>128)) { if(old_cluster_size>0) { cluster_size=old_cluster_size; ecrit_rapport("Assumes previous cluster size was good\n"); } else { ecrit_rapport("Can't get cluster size\n"); return 0; } } } if(upart_type==UP_FAT32) { /* Use first fat */ fat32_free_info(disk_car,partition,reserved,data_size/cluster_size,&next_free,&free_count); /* FAT32 : Find root cluster */ root_cluster=fat32_find_root_cluster(disk_car,partition,cluster_size,data_size/cluster_size,start_data,reserved,interface,debug); /* if(debug>1) { ecrit_rapport("override root_cluster=2\n"); root_cluster=2; } */ } if(interface) { wmove(stdscr,9,0); wclrtoeol(stdscr); wrefresh(stdscr); } create_fat_boot_sector(disk_car,partition, reserved, debug,dir_entries,root_cluster,cluster_size,fat_length,interface,upart_type); if(debug) { ecrit_rapport("\n"); aff_part_rapport(disk_car,partition); } } return 0; } static int write_FAT_boot_code_aux(unsigned char *buffer) { const unsigned char boot_code[SECTOR_SIZE]= { 0xeb, 0x3c, 0x90, 0x6d, 0x6b, 0x64, 0x6f, 0x73, 0x66, 0x73, 0x00, 0x00, 0x02, 0x08, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0xf8, 0xcc, 0x00, 0x3f, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x5f, 0x06, 0x00, 0x00, 0x00, 0x29, 0xf8, 0x3f, 0x7c, 0x3e, 'T', 'E', 'S', 'T', 'D', 'I', 'S', 'K', 0x20, 0x20, 0x20, 0x46, 0x41, 0x54, 0x31, 0x36, 0x20, 0x20, 0x20, 0x0e, 0x1f, 0xbe, 0x5b, 0x7c, 0xac, 0x22, 0xc0, 0x74, 0x0b, 0x56, 0xb4, 0x0e, 0xbb, 0x07, 0x00, 0xcd, 0x10, 0x5e, 0xeb, 0xf0, 0x32, 0xe4, 0xcd, 0x16, 0xcd, 0x19, 0xeb, 0xfe, 'T', 'h', 'i', 's', ' ', 'i', 's', ' ', 'n', 'o', 't', ' ', 'a', ' ', 'b', 'o', 'o', 't', 'a', 'b', 'l', 'e', ' ', 'd', 'i', 's', 'k', '.', ' ', ' ', 'P', 'l', 'e', 'a', 's', 'e', ' ', 'i', 'n', 's', 'e', 'r', 't', ' ', 'a', ' ', 'b', 'o', 'o', 't', 'a', 'b', 'l', 'e', ' ', 'f', 'l', 'o', 'p', 'p', 'y', ' ', 'a', 'n', 'd', 0x0d, 0x0a, 'p', 'r', 'e', 's', 's', ' ', 'a', 'n', 'y', ' ', 'k', 'e', 'y', ' ', 't', 'o', ' ', 't', 'r', 'y', ' ', 'a', 'g', 'a', 'i', 'n', ' ', '.', '.', '.', ' ', 0x0d, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa }; memcpy(buffer,&boot_code,SECTOR_SIZE); return 0; }